package cn.jilian.sys.service.impl;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.jilian.common.util.MapUtil;
import cn.jilian.dao.LinkDAO;
import cn.jilian.dao.MaceDAO;
import cn.jilian.dao.RoleDAO;
import cn.jilian.entity.Link;
import cn.jilian.entity.Mace;
import cn.jilian.entity.Role;
import cn.jilian.sys.service.MaceService;


@Service
public class MaceServiceImpl implements MaceService {

	@Autowired
	private RoleDAO roleDAO;
	@Autowired
	private MaceDAO maceDAO;
	@Autowired
	private LinkDAO linkDAO;
	
	public static void main(String[] args) {
		Integer a1=0b001101;
		Integer a2=0b000111;
		System.out.println(Integer.toBinaryString(a1&a2));
		System.out.println(Integer.toBinaryString(a1|a2));
	}
	
	@Override
	public Mace save(long uid, long fid, int act, long meta) {
		
		Mace mace=maceDAO.findByFidAndUid(fid, uid);
		if(mace!=null) {
			Integer oldAct=mace.getAct();
			if(oldAct!=null) {
				if((oldAct&act)==act) {
					return mace;
				}else {
					act=oldAct|act;
				}
			}
			
		}
		mace.setUid(uid);
		mace.setFid(fid);
		mace.setAct(act);
		mace.setMeta(meta);
		mace.setRank(Mace.MENU_MACE_RANK);
		return maceDAO.save(mace);
	}

	@Override
	public int deleteRole(long id) {
		Role role=roleDAO.findOne(id);
		if(role==null)
		return 0;
		maceDAO.deleteByUid(id);
		roleDAO.delete(role);
		linkDAO.deleteByRelate(id);
		return 1;
	}

	@Override
	public int saveUserRoles(long uid, Collection<Long> adds, Collection<Long> dels) {
		List<Link> links=linkDAO.findBySourceAndRelateIn(uid, adds);
		Map<Long,Link> glinkMap=groupByRelate(links);
		for(Long id:adds) {
			Link link=glinkMap.get(id);
			if(link==null) {
				link=new Link();
				link.setSource(uid);
				link.setRelate(id);
				link.setRank(Link.ROLE_LINK_RANK);
				linkDAO.save(link);
			}
		}
		linkDAO.deleteBySourceAndRelateIn(uid, dels);
		return 1;
	}
	
	private Map<Long,Link> groupByRelate(List<Link> links){
		Map<Long,Link> rs=new HashMap<>();
		for(Link link:links) {
			Long fid=link.getRelate();
			rs.put(fid, link);
		}
		return rs;
	}

	@Override
	public Collection<Long> getRoles(long uid) {
		List<Link> list=linkDAO.findBySourceAndRank(uid, Link.ROLE_LINK_RANK);
		if(CollectionUtils.isEmpty(list))
		return Collections.emptyList();
		Collection<Long> ids=new HashSet<>(list.size());
		for(Link link:list) {
			ids.add(link.getRelate());
		}
		return ids;
	}

	@Override
	public Collection<Long> getMaces(long uid, int rankId) {
		List<Mace> maces=maceDAO.findByUidAndRank(uid, rankId);
		if(CollectionUtils.isEmpty(maces)) {
			return Collections.emptyList();
		}
		Collection<Long> ids=new HashSet<>(maces.size());
		for(Mace m:maces) {
			if(m.getAct()>0)
				ids.add(m.getFid());
		}
		return ids;
	}

	@Override
	public Map<Long, Integer> getMaceMap(long uid, int rankId) {
		List<Mace> maces=maceDAO.findByUidAndRank(uid, rankId);
		if(CollectionUtils.isEmpty(maces)) {
			return Collections.emptyMap();
		}
		Map<Long,Integer> ids=new HashMap<>(maces.size());
		for(Mace m:maces) {
			ids.put(m.getFid(), m.getAct());
		}
		return ids;
	}

	@Override
	@Transactional
	public int saveMaces(long uid, Collection<Long> adds, Collection<Long> dels,Integer rank) {
		List<Mace> maces=maceDAO.findByUidAndFidIn(uid, adds);
		Map<Long,Mace> maceMap=groupMacesByFid(maces);
		for(Long add:adds) {
			Mace mace=maceMap.get(add);
			if(mace==null) {
				mace=new Mace();
				mace.setFid(add);
				mace.setUid(uid);
				mace.setRank(rank);
				mace.setAct(1);
				mace.setFlag(1);
				maceDAO.save(mace);
			}
		}
		maceDAO.deleteByUidAndFidIn(uid, dels);
		return 1;
	}
	
	private Map<Long,Mace> groupMacesByFid(List<Mace> maces){
		if(CollectionUtils.isEmpty(maces)) {
			return Collections.emptyMap();
		}
		Map<Long,Mace> rs=new HashMap<>(maces.size());
		for(Mace m:maces) {
			rs.put(m.getFid(), m);
		}
		return rs;
	}

	@Override
	public Role createRole(Role role) {
		
		return roleDAO.save(role);
	}

	@Override
	@Transactional
	public int deleteRoles(Collection<Long> ids) {
		maceDAO.deleteByUidIn(ids);
		linkDAO.deleteByRelateIn(ids);
		roleDAO.deleteByIdIn(ids);
		return 1;
	}

	@Override
	public int saveMaceMap(long uid, Map<Long, Integer> maceMap,Integer rank,Long meta) {
		List<Mace> maces=maceDAO.findByUidAndFidIn(uid, maceMap.keySet());
		int r=0;
		if(CollectionUtils.isEmpty(maces)) {
			for(Map.Entry<Long, Integer> e:maceMap.entrySet()) {
				Long fid=e.getKey();
				Integer act=e.getValue();
				if(act!=null&&act.intValue()>0)
				maceDAO.save(new Mace(uid,fid,act,rank,meta));
				r+=1;
			}
		}else {
			Map<Long,Mace> oldMaceMap=MapUtil.groupListBeanBy(maces, "fid", Long.class);
			for(Map.Entry<Long, Integer> e:maceMap.entrySet()) {
				Long fid=e.getKey();
				Integer act=e.getValue();
				Mace oldMace=oldMaceMap.get(fid);
				if(oldMace==null) {
					if(act!=null&&act.intValue()>0)
					maceDAO.save(new Mace(uid,fid,act,rank,meta));
				}else {
					if(act!=null) {
						if(act.intValue()>0) {
							Integer oldAct=oldMace.getAct();
							Integer newAct=oldAct|act;
							oldMace.setAct(newAct);
						}else{
							Integer oldAct=oldMace.getAct();
							Integer newAct=oldAct&~(-act);
							oldMace.setAct(newAct);
						}
						maceDAO.save(oldMace);
						r+=1;
					}
				}
				
			}
		}
		return r;
	}

}
